package com.android.geotrack;

import java.util.LinkedList;
import java.util.List;


import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ZoomControls;

import com.android.geotrack.user.LoadUsersRunnable;
import com.android.geotrack.user.User;
import com.android.geotrack.user.UserOverlay;
import com.android.geotrack.user.UserOverlayItem;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

/**
 * GeoActivity class.
 * 
 * "Geo" tab in app.
 * Loads Google map and draws a clickable marker for each user.
 * 
 * @author	Owner
 */
public class GeoActivity extends MapActivity
{		
	private LinearLayout linearLayout;
	private MapView mapView;
	private ZoomControls mZoom;
	private List<Overlay> mapOverlays;
	private Drawable drawable;
	private UserOverlay userOverlay;
	private MapController mc;
	private Geocoder gc;
	
	private LocationManager locMan;
	
	private Thread loadUsers;
	private ProgressDialog pd;
	
	/** List of related users. */
	private LinkedList<User> users;
	
	/**
	 * Called on creation of tab.
	 * Draws Google map and exit button.
	 */
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.geo);
		loadUsers = new Thread(new LoadUsersRunnable(GeoTrack.currentUser, this));
		Log.v("Activity creation", "GeoActivity");
		
		// init map controls
        gc = new Geocoder(this);
        linearLayout = (LinearLayout) findViewById(R.id.zoomview);
    	mapView = (MapView) findViewById(R.id.mapview);
        mc = mapView.getController();
    	mZoom = (ZoomControls) mapView.getZoomControls();
    	linearLayout.addView(mZoom);
    	mapOverlays = mapView.getOverlays();
    	
    	// set location listener
    	locMan = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    	
    	// exit button
    	final Button buttonExit = (Button) findViewById(R.id.exitButton);
    	buttonExit.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {            	
            	finish();
            }
        });
	}
	
	/**
	 * Called every time the "Geo"-tab is opened.
	 */
	protected void onResume()
	{
		super.onResume();
		
		// update location of user
    	locMan.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100, 1, gpsListener); 
		
    	// redraw map
    	redraw();
	}
	
	/**
	 * Converts latitude/longitude coordinates in decimal degrees to "microdegrees".
	 * 
	 * @param 	co
	 * 			Latitude or longitude coordinates in decimal degrees.
	 * @return	The coordinate in microdegrees (x 10E6).
	 */
	private int toMicroDegrees(double co)
	{
		return (int)(co * 1000000);
	}
		
	/** Called every time the loadUsers thread is finished. */
	public Handler messageHandler = new Handler() 
		{
			@Override
			public void handleMessage(Message msg)
			{
				pd.dismiss();
				
				switch(msg.what) {
				case 1337:
					GeoActivity.this.users = (LinkedList<User>) msg.obj;
					drawUsers();
					break;
				}
			}
		};
		
	/**
	 * Redraws all markers on the map.
	 */
	public void redraw()
	{
		// draw "me" marker
    	mapOverlays.clear();
    	drawable = this.getResources().getDrawable(R.drawable.marker_user);
    	userOverlay = new UserOverlay(this, drawable);
    	GeoPoint me = new GeoPoint(toMicroDegrees(GeoTrack.currentUser.getLatitude()), 
    			toMicroDegrees(GeoTrack.currentUser.getLongitude()));
    	UserOverlayItem meOverlay = new UserOverlayItem(me, "Me!", "Me", GeoTrack.currentUser);
    	Drawable meMarker = this.getResources().getDrawable(R.drawable.marker_me);
    	userOverlay.setMarker(meOverlay, meMarker);
    	userOverlay.addOverlay(meOverlay);
    	mapView.computeScroll();
    	mapView.clearFocus();
    	mapOverlays.add(userOverlay);
    	
    	// load users if possible
		if(!LoadUsersRunnable.lur_started) {
			loadUsers = new Thread(new LoadUsersRunnable(GeoTrack.currentUser, this));
			pd = ProgressDialog.show(this, "Working..", "Loading related users!", true, false);
			loadUsers.start();
		}
    	
    	navigateToLocation(GeoTrack.currentUser.getLatitude(), 
    			GeoTrack.currentUser.getLongitude(), mapView);
	}
	
	/**
	 * Draws a clickable maker on the Google map for each user in our database.
	 */
	public void drawUsers()
	{
		GeoPoint gp;
    	UserOverlayItem overlayItem;
    	
		for(User u : users) {
			gp = new GeoPoint(toMicroDegrees(u.getLatitude()), toMicroDegrees(u.getLongitude()));
			overlayItem = new UserOverlayItem(gp, u.getName(), u.getName(), u);
			userOverlay.addOverlay(overlayItem);
		}
		
    	mapView.computeScroll();
    	mapView.clearFocus();
    	
    	navigateToLocation(GeoTrack.currentUser.getLatitude(), 
    			GeoTrack.currentUser.getLongitude(), mapView);
	}
	
	/** 
	 * Navigates a given MapView to the specified longitude and latitude.
	 * 
	 * @param  	latitude
	 * @param	longitude
	 * @param	mv
	 */ 
	public void navigateToLocation(double latitude, double longitude, MapView mv)
	{  
		GeoPoint p = new GeoPoint(toMicroDegrees(latitude), toMicroDegrees(longitude)); //new GeoPoint 
		mv.displayZoomControls(true); //display Zoom (seems that it doesn't work yet) 
		MapController mc = mv.getController(); 
		mc.animateTo(p); //move map to the given point 
		int zoomlevel = mv.getMaxZoomLevel(); //detect maximum zoom level 
		mc.setZoom(zoomlevel - 7); //zoom 
		mv.setSatellite(false); //display only "normal" mapview
        Log.v("Location", "Location set to " + latitude + ", " + longitude + "!");
	}
	
	/** Listens for GPS updates. */
	private LocationListener gpsListener = new LocationListener()
		{
			boolean locationChanged = false; 
			public void onLocationChanged(Location location)
			{
				double latitude = location.getLatitude();
				double longitude = location.getLongitude();
				
				// update current user
				GeoTrack.currentUser.setLatitude(latitude);
				GeoTrack.currentUser.setLongitude(longitude);
				
				// redraw Google map
				redraw();
			}
			public void onProviderDisabled(String provider){}
			public void onProviderEnabled(String provider){}
			public void onStatusChanged(String provider, int status, Bundle extras){}
		};
	
	/**
	 * Obligatory.
	 */
	@Override
	protected boolean isRouteDisplayed()
	{
		return false;
	}

}